package com.supporter.sysbench;

import com.supporter.sysbench.result.Statistics;
import com.supporter.sysbench.work.SQLExecutor;
import com.supporter.sysbench.work.Worker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author xunaidong
 * @date 2021/8/8
 */
@Component
public class SysbenchCommandLine implements CommandLineRunner {

    private final static Logger log = LoggerFactory.getLogger(SysbenchCommandLine.class);

    private final ThreadPoolContext threadPoolContext;
    private final GlobalProperties globalProperties;
    private final Statistics statistics;
    private final SQLExecutor sqlExecutor;

    public SysbenchCommandLine(ThreadPoolContext threadPoolContext, GlobalProperties globalProperties, Statistics statistics,
                               SQLExecutor sqlExecutor) {
        this.threadPoolContext = threadPoolContext;
        this.globalProperties = globalProperties;
        this.statistics = statistics;
        this.sqlExecutor = sqlExecutor;
    }

    @Override
    public void run(String... args) throws Exception {
        if(Command.PREPARE==globalProperties.getCommand()){
            long start = System.currentTimeMillis();
            for(int i=1;i<=globalProperties.getTableNumber();i++){
                threadPoolContext.execute(new Worker(globalProperties,sqlExecutor,i));
            }
            for(;;){
                if(statistics.completeTable.get() == globalProperties.getTableNumber()){
                    log.info("数据初始化完成,共{}张表,总耗时{}s,请手动退出.",globalProperties.getTableNumber(),(System.currentTimeMillis()-start)/1000);
                    break;
                }else{
                    TimeUnit.SECONDS.sleep(5);
                    log.info("已初始化完成"+statistics.completeTable.get()+"张表.");
                }
            }
        }

        if(Command.READ_WRITE==globalProperties.getCommand()||Command.READ_ONLY==globalProperties.getCommand()){
            long start = System.currentTimeMillis();
            log.info("启动sysbench多线程任务.");
            for(int i=1;i<=globalProperties.getThreads();i++){
                threadPoolContext.execute(new Worker(globalProperties,sqlExecutor,i));
            }
            log.info("启动sysbench多线程任务完毕，共启动{}个任务.",globalProperties.getThreads());
            TimeUnit.SECONDS.sleep(globalProperties.getReportInterval());
            for(;;){
                long split = (System.currentTimeMillis()-start)/1000;
                System.out.println("[ "+((System.currentTimeMillis()-start)/1000)+
                        "s ] thds: "+globalProperties.getThreads()+" tps: "+String.format("%.2f",(float)statistics.txcnt.get()/split)+
                        " qps: "+String.format("%.2f",(float)statistics.qrcnt.get()/split)+
                        " (r/w/o: "+String.format("%.2f",(float)statistics.rdcnt.get()/split)+"/"+
                        String.format("%.2f",(float)statistics.wrcnt.get()/split)+"/"+String.format("%.2f",(float)statistics.otcnt.get()/split)+") " +
                        "lat(ms): "+String.format("%.2f", (float)statistics.latms.get()/statistics.txcnt.get())+
                        " err/s: "+String.format("%.2f",(float)statistics.ercnt.get()/split));
                if(System.currentTimeMillis()-start>globalProperties.getDuration()*1000){
                    System.out.println("正在等待线程关闭.");
                    TimeUnit.SECONDS.sleep(globalProperties.getReportInterval());
                    System.out.println("[ 测试总时长:"+globalProperties.getDuration()+
                            "s ] 并发数量: "+globalProperties.getThreads()+" 事物总数: "+statistics.txcnt.get()+
                            " 响应总数: "+statistics.qrcnt.get()+" 读库总数:"+statistics.rdcnt.get()+" 写库总数:"+statistics.wrcnt.get()+
                            " 其他操作总数:"+statistics.otcnt.get()+" 错误总数:"+statistics.ercnt.get()+" 响应总时长(ms):"+statistics.latms.get());
                    System.out.println("已完成测试,请手动关闭程序.");
                    break;
                }else{
                    TimeUnit.SECONDS.sleep(globalProperties.getReportInterval());
                }
            }
        }
    }
}
